package cn.tedu.charging.cost.repository.impl;

import cn.tedu.charging.common.pojo.po.ChargingCostRulePO;
import cn.tedu.charging.cost.mapper.CostRuleMapper;
import cn.tedu.charging.cost.repository.CostRuleRepository;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.stream.Collectors;

@Repository
@Slf4j
public class CostRuleRepositoryImpl implements CostRuleRepository {
    @Autowired
    private CostRuleMapper costRuleMapper;
    @Autowired
    private RedisTemplate<String,ChargingCostRulePO> redisTemplate;
    @Override
    public ChargingCostRulePO getCostRule(Integer stationId, Integer hour) {
        //1.方案,使用数据库做计价规则的查询
        /*
            尖上午 8 12     8<=hour<12
            尖下午 14 18    14<=hour<18
            峰    18 24    18<=hour<24
            平    12 14    12<=hour<14
            谷    0  8     0<=hour<8
         */
        /*//select * from charging_cost_rule where station_id=? and start_time<=?<end_time
        QueryWrapper queryWrapper=new QueryWrapper();
        //station_id=#{stationId} 由于测试数据有问题 写死stationId=5
        queryWrapper.eq("station_id", 5);
        //start_time<=hour<end_time
        queryWrapper.le("start_time",hour);
        queryWrapper.gt("end_time",hour);
        return costRuleMapper.selectOne(queryWrapper);*/
        //2.采用旁路缓存(key绑定业务是什么??) key值怎么设计 value值类型是什么
        //思路: 使用场站id 存储所有该场站的计价规则,也可以使用枪id 记录所有枪的计价规则
        //key的设计 可以绑定场站id 枪id value可以使用list将所有规则列表存储 每个元素就是po对象
        //使用id查询缓存的list 一定包含当前需要的规则,如果没有 查询数据库,往缓存填充
        //2.1查询缓存 判断是否命中 缓存数据类型list
        String costRuleKey="charging:cost:rule:"+stationId;
        //lrange costRuleKey 0 -1 查询缓存所有的list元素
        ListOperations<String, ChargingCostRulePO> listOps = redisTemplate.opsForList();
        List<ChargingCostRulePO> pos = listOps.range(costRuleKey, 0, -1);
        //筛选 可以使用stream() filter
        if (pos!=null&& pos.size()>0){
            log.debug("本次缓存命中,直接使用数据");
            //满足时间判断条件的 start_time<=hour and end_time>hour
            return pos.stream().filter(po->{
                //计算筛选规则
                return po.getStartTime()<=hour&&po.getEndTime()>hour;
            }).collect(Collectors.toList()).get(0);
        }else{
            log.debug("本次缓存没命中,先读数据库");
            QueryWrapper<ChargingCostRulePO> queryWrapper=new QueryWrapper();
            queryWrapper.eq("station_id", stationId);
            pos = costRuleMapper.selectList(queryWrapper);
            //存储到缓存供后续使用
            listOps.leftPushAll(costRuleKey,pos);
            return pos.stream().filter(po->{
                //计算筛选规则
                return po.getStartTime()<=hour&&po.getEndTime()>hour;
            }).collect(Collectors.toList()).get(0);
        }
    }
}
